@adminforth/markdown 1.10.11 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.log +2 -2
- package/custom/MarkdownRenderer.vue +4 -0
- package/dist/custom/MarkdownRenderer.vue +4 -0
- package/dist/index.js +59 -40
- package/index.ts +24 -12
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -14,5 +14,5 @@ custom/tsconfig.json
|
|
|
14
14
|
custom/utils/
|
|
15
15
|
custom/utils/monacoMarkdownToggle.ts
|
|
16
16
|
|
|
17
|
-
sent 52,
|
|
18
|
-
total size is 52,
|
|
17
|
+
sent 52,957 bytes received 180 bytes 106,274.00 bytes/sec
|
|
18
|
+
total size is 52,265 speedup is 0.98
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
prose-hr:my-1
|
|
13
13
|
leading-tight
|
|
14
14
|
dark: dark:text-gray-300
|
|
15
|
+
dark:[&_th]:text-white
|
|
16
|
+
dark:[&_td]:text-white
|
|
17
|
+
dark:[&_thead]:border-b-gray-600
|
|
18
|
+
dark:[&_code]:text-white
|
|
15
19
|
dark:[&_h1]:text-white dark:[&_h2]:text-gray-100 dark:[&_h3]:text-gray-200
|
|
16
20
|
dark:[&_a]:text-white dark:[&_a:hover]:text-white
|
|
17
21
|
dark:[&_pre]:bg-black dark:[&_pre]:border dark:[&_border-slate-800]
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
prose-hr:my-1
|
|
13
13
|
leading-tight
|
|
14
14
|
dark: dark:text-gray-300
|
|
15
|
+
dark:[&_th]:text-white
|
|
16
|
+
dark:[&_td]:text-white
|
|
17
|
+
dark:[&_thead]:border-b-gray-600
|
|
18
|
+
dark:[&_code]:text-white
|
|
15
19
|
dark:[&_h1]:text-white dark:[&_h2]:text-gray-100 dark:[&_h3]:text-gray-200
|
|
16
20
|
dark:[&_a]:text-white dark:[&_a:hover]:text-white
|
|
17
21
|
dark:[&_pre]:bg-black dark:[&_pre]:border dark:[&_border-slate-800]
|
package/dist/index.js
CHANGED
|
@@ -19,11 +19,24 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
19
19
|
}
|
|
20
20
|
// Placeholder for future Upload Plugin API integration.
|
|
21
21
|
// For now, treat all extracted URLs as plugin-owned public URLs.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
isUrlFromPlugin(url) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
if (!this.uploadPlugin)
|
|
25
|
+
return false;
|
|
26
|
+
try {
|
|
27
|
+
const uploadPlugin = this.uploadPlugin;
|
|
28
|
+
if (typeof uploadPlugin.isInternalUrl === 'function') {
|
|
29
|
+
return yield uploadPlugin.isInternalUrl(url);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new Error('Please update upload plugin and storage adapter');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
console.error(`[MarkdownPlugin] Error checking URL ${url}:`, err);
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
});
|
|
27
40
|
}
|
|
28
41
|
validateConfigAfterDiscover(adminforth, resourceConfig) {
|
|
29
42
|
this.adminforth = adminforth;
|
|
@@ -150,18 +163,22 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
150
163
|
};
|
|
151
164
|
const shouldTrackUrl = (url) => {
|
|
152
165
|
try {
|
|
153
|
-
return this.
|
|
166
|
+
return this.isUrlFromPlugin(url);
|
|
154
167
|
}
|
|
155
168
|
catch (err) {
|
|
156
169
|
console.error('Error checking URL ownership', url, err);
|
|
157
170
|
return false;
|
|
158
171
|
}
|
|
159
172
|
};
|
|
160
|
-
const getKeyFromTrackedUrl = (rawUrl) => {
|
|
173
|
+
const getKeyFromTrackedUrl = (rawUrl) => __awaiter(this, void 0, void 0, function* () {
|
|
161
174
|
const srcTrimmed = rawUrl.trim().replace(/^<|>$/g, '');
|
|
162
175
|
if (!srcTrimmed || srcTrimmed.startsWith('data:') || srcTrimmed.startsWith('javascript:')) {
|
|
163
176
|
return null;
|
|
164
177
|
}
|
|
178
|
+
const isInternal = yield this.isUrlFromPlugin(srcTrimmed);
|
|
179
|
+
if (!isInternal) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
165
182
|
if (!shouldTrackUrl(srcTrimmed)) {
|
|
166
183
|
return null;
|
|
167
184
|
}
|
|
@@ -171,7 +188,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
171
188
|
return null;
|
|
172
189
|
}
|
|
173
190
|
return decodeURIComponent(key);
|
|
174
|
-
};
|
|
191
|
+
});
|
|
175
192
|
const upsertMeta = (byKey, key, next) => {
|
|
176
193
|
var _a, _b;
|
|
177
194
|
const existing = byKey.get(key);
|
|
@@ -201,38 +218,40 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
201
218
|
return cleaned || null;
|
|
202
219
|
};
|
|
203
220
|
function getAttachmentMetas(markdown) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
// Markdown image syntax:  or  or 
|
|
209
|
-
const imageRegex = /!\[([^\]]*)\]\(\s*([^\s)]+)\s*(?:\s+(?:\"([^\"]*)\"|'([^']*)'))?\s*\)/g;
|
|
210
|
-
// HTML embedded media links.
|
|
211
|
-
const htmlSrcRegex = /<(?:source|video)\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s"'=<>`]+))[^>]*>/gi;
|
|
212
|
-
const byKey = new Map();
|
|
213
|
-
for (const match of markdown.matchAll(imageRegex)) {
|
|
214
|
-
const altRaw = (_a = match[1]) !== null && _a !== void 0 ? _a : '';
|
|
215
|
-
const srcRaw = match[2];
|
|
216
|
-
const titleRaw = normalizeAttachmentTitleForDb((_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null);
|
|
217
|
-
const key = getKeyFromTrackedUrl(srcRaw);
|
|
218
|
-
if (!key) {
|
|
219
|
-
continue;
|
|
221
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
222
|
+
var _a, _b, _c, _d, _e, _f;
|
|
223
|
+
if (!markdown) {
|
|
224
|
+
return [];
|
|
220
225
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
// Markdown image syntax:  or  or 
|
|
227
|
+
const imageRegex = /!\[([^\]]*)\]\(\s*([^\s)]+)\s*(?:\s+(?:\"([^\"]*)\"|'([^']*)'))?\s*\)/g;
|
|
228
|
+
// HTML embedded media links.
|
|
229
|
+
const htmlSrcRegex = /<(?:source|video)\b[^>]*\bsrc\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s"'=<>`]+))[^>]*>/gi;
|
|
230
|
+
const byKey = new Map();
|
|
231
|
+
for (const match of markdown.matchAll(imageRegex)) {
|
|
232
|
+
const altRaw = (_a = match[1]) !== null && _a !== void 0 ? _a : '';
|
|
233
|
+
const srcRaw = match[2];
|
|
234
|
+
const titleRaw = normalizeAttachmentTitleForDb((_c = ((_b = match[3]) !== null && _b !== void 0 ? _b : match[4])) !== null && _c !== void 0 ? _c : null);
|
|
235
|
+
const key = yield getKeyFromTrackedUrl(srcRaw);
|
|
236
|
+
if (!key) {
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
upsertMeta(byKey, key, {
|
|
240
|
+
alt: altRaw,
|
|
241
|
+
title: titleRaw,
|
|
242
|
+
});
|
|
232
243
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
let srcMatch;
|
|
245
|
+
while ((srcMatch = htmlSrcRegex.exec(markdown)) !== null) {
|
|
246
|
+
const srcRaw = (_f = (_e = (_d = srcMatch[1]) !== null && _d !== void 0 ? _d : srcMatch[2]) !== null && _e !== void 0 ? _e : srcMatch[3]) !== null && _f !== void 0 ? _f : '';
|
|
247
|
+
const key = yield getKeyFromTrackedUrl(srcRaw);
|
|
248
|
+
if (!key) {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
upsertMeta(byKey, key, {});
|
|
252
|
+
}
|
|
253
|
+
return [...byKey.values()];
|
|
254
|
+
});
|
|
236
255
|
}
|
|
237
256
|
const createAttachmentRecords = (adminforth, options, recordId, metas, adminUser) => __awaiter(this, void 0, void 0, function* () {
|
|
238
257
|
if (!metas.length) {
|
|
@@ -334,7 +353,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
334
353
|
});
|
|
335
354
|
(resourceConfig.hooks.create.afterSave).push((_a) => __awaiter(this, [_a], void 0, function* ({ record, adminUser }) {
|
|
336
355
|
// find all s3Paths in the html
|
|
337
|
-
const metas = getAttachmentMetas(record[this.options.fieldName]);
|
|
356
|
+
const metas = yield getAttachmentMetas(record[this.options.fieldName]);
|
|
338
357
|
const keys = metas.map(m => m.key);
|
|
339
358
|
process.env.HEAVY_DEBUG && console.log('📸 Found attachment keys', keys);
|
|
340
359
|
// create attachment records
|
|
@@ -355,7 +374,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
355
374
|
Filters.EQ(this.options.attachments.attachmentResourceIdFieldName, resourceConfig.resourceId)
|
|
356
375
|
]);
|
|
357
376
|
const existingKeys = existingAparts.map((a) => a[this.options.attachments.attachmentFieldName]);
|
|
358
|
-
const metas = getAttachmentMetas(record[this.options.fieldName]);
|
|
377
|
+
const metas = yield getAttachmentMetas(record[this.options.fieldName]);
|
|
359
378
|
const newKeys = metas.map(m => m.key);
|
|
360
379
|
process.env.HEAVY_DEBUG && console.log('📸 Existing keys (from db)', existingKeys);
|
|
361
380
|
process.env.HEAVY_DEBUG && console.log('📸 Found new keys (from text)', newKeys);
|
package/index.ts
CHANGED
|
@@ -19,11 +19,19 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
19
19
|
|
|
20
20
|
// Placeholder for future Upload Plugin API integration.
|
|
21
21
|
// For now, treat all extracted URLs as plugin-owned public URLs.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
async isUrlFromPlugin(url: string): Promise<boolean> {
|
|
23
|
+
if (!this.uploadPlugin) return false;
|
|
24
|
+
try {
|
|
25
|
+
const uploadPlugin = this.uploadPlugin as any;
|
|
26
|
+
if (typeof uploadPlugin.isInternalUrl === 'function') {
|
|
27
|
+
return await uploadPlugin.isInternalUrl(url);
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error ('Please update upload plugin and storage adapter')
|
|
30
|
+
}
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.error(`[MarkdownPlugin] Error checking URL ${url}:`, err);
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
27
35
|
}
|
|
28
36
|
|
|
29
37
|
validateConfigAfterDiscover(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
|
|
@@ -168,18 +176,22 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
168
176
|
|
|
169
177
|
const shouldTrackUrl = (url: string) => {
|
|
170
178
|
try {
|
|
171
|
-
return this.
|
|
179
|
+
return this.isUrlFromPlugin(url);
|
|
172
180
|
} catch (err) {
|
|
173
181
|
console.error('Error checking URL ownership', url, err);
|
|
174
182
|
return false;
|
|
175
183
|
}
|
|
176
184
|
};
|
|
177
185
|
|
|
178
|
-
const getKeyFromTrackedUrl = (rawUrl: string): string | null => {
|
|
186
|
+
const getKeyFromTrackedUrl = async (rawUrl: string): Promise<string | null> => {
|
|
179
187
|
const srcTrimmed = rawUrl.trim().replace(/^<|>$/g, '');
|
|
180
188
|
if (!srcTrimmed || srcTrimmed.startsWith('data:') || srcTrimmed.startsWith('javascript:')) {
|
|
181
189
|
return null;
|
|
182
190
|
}
|
|
191
|
+
const isInternal = await this.isUrlFromPlugin(srcTrimmed);
|
|
192
|
+
if (!isInternal) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
183
195
|
if (!shouldTrackUrl(srcTrimmed)) {
|
|
184
196
|
return null;
|
|
185
197
|
}
|
|
@@ -225,7 +237,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
225
237
|
return cleaned || null;
|
|
226
238
|
};
|
|
227
239
|
|
|
228
|
-
function getAttachmentMetas(markdown: string): AttachmentMeta[] {
|
|
240
|
+
async function getAttachmentMetas(markdown: string): Promise<AttachmentMeta[]> {
|
|
229
241
|
if (!markdown) {
|
|
230
242
|
return [];
|
|
231
243
|
}
|
|
@@ -242,7 +254,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
242
254
|
const srcRaw = match[2];
|
|
243
255
|
const titleRaw = normalizeAttachmentTitleForDb((match[3] ?? match[4]) ?? null);
|
|
244
256
|
|
|
245
|
-
const key = getKeyFromTrackedUrl(srcRaw);
|
|
257
|
+
const key = await getKeyFromTrackedUrl(srcRaw);
|
|
246
258
|
if (!key) {
|
|
247
259
|
continue;
|
|
248
260
|
}
|
|
@@ -255,7 +267,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
255
267
|
let srcMatch: RegExpExecArray | null;
|
|
256
268
|
while ((srcMatch = htmlSrcRegex.exec(markdown)) !== null) {
|
|
257
269
|
const srcRaw = srcMatch[1] ?? srcMatch[2] ?? srcMatch[3] ?? '';
|
|
258
|
-
const key = getKeyFromTrackedUrl(srcRaw);
|
|
270
|
+
const key = await getKeyFromTrackedUrl(srcRaw);
|
|
259
271
|
if (!key) {
|
|
260
272
|
continue;
|
|
261
273
|
}
|
|
@@ -390,7 +402,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
390
402
|
|
|
391
403
|
(resourceConfig.hooks.create.afterSave).push(async ({ record, adminUser }: { record: any, adminUser: AdminUser }) => {
|
|
392
404
|
// find all s3Paths in the html
|
|
393
|
-
const metas = getAttachmentMetas(record[this.options.fieldName]);
|
|
405
|
+
const metas = await getAttachmentMetas(record[this.options.fieldName]);
|
|
394
406
|
const keys = metas.map(m => m.key);
|
|
395
407
|
process.env.HEAVY_DEBUG && console.log('📸 Found attachment keys', keys);
|
|
396
408
|
// create attachment records
|
|
@@ -416,7 +428,7 @@ export default class MarkdownPlugin extends AdminForthPlugin {
|
|
|
416
428
|
]);
|
|
417
429
|
const existingKeys = existingAparts.map((a: any) => a[this.options.attachments.attachmentFieldName]);
|
|
418
430
|
|
|
419
|
-
const metas = getAttachmentMetas(record[this.options.fieldName]);
|
|
431
|
+
const metas = await getAttachmentMetas(record[this.options.fieldName]);
|
|
420
432
|
const newKeys = metas.map(m => m.key);
|
|
421
433
|
|
|
422
434
|
process.env.HEAVY_DEBUG && console.log('📸 Existing keys (from db)', existingKeys)
|